﻿using GN.Pay.TradeChannel.Transfers;
using GN.Pay.TradeChannel.WeiXin.Response;
using GN.Pay.Utils.Net.Http;
using GN.Pay.Utils.Security;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;

namespace GN.Pay.TradeChannel.WeiXin.Request
{
    /// <summary>
    /// 转账请求
    /// </summary>
    [Serializable]
    class TransfersRequest : AServiceRequest
    {
        private readonly ITransfersApplyInfo apply;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="apply"></param>
        /// <param name="config"></param>
        public TransfersRequest(ITransfersApplyInfo apply,
            WeiXinConfigure config)
        {
            this.apply = apply;
            Mch_AppId = config.ConfigureInfo.AppId;
            MchId = config.ConfigureInfo.AccountId;
            Device_Info = "";
            Partner_Trade_No = apply.TransfersNo;
            OpenId = apply.AccountNo;
          //  Check_Name = "FORCE_CHECK";
            Check_Name = "NO_CHECK";
          //  Re_User_Name = apply.AccountName;
            Amount = GetMoneyForCent(apply.TransfersMoney);
            Desc = apply.Summary;
            Spbill_Create_Ip = apply.ServerIp;
        }

        /// <summary>
        /// 微信分配的公众账号ID（企业号corpid即为此appId）
        /// </summary>
        [Required(ErrorMessage = "微信分配的公众账号ID（企业号corpid即为此appId） 不能这空")]
        public string Mch_AppId { get; set; }

        /// <summary>
        /// 微信支付分配的商户号
        /// </summary>
        [Required(ErrorMessage = "微信支付分配的商户号 不能这空")]
        public string MchId { get; set; }

        /// <summary>
        /// 微信支付分配的终端设备号，
        /// </summary>
        public string Device_Info { get; set; }

        /// <summary>
        /// 商户订单号，需保持唯一性(只能是字母或者数字，不能包含有符号)
        /// </summary>
        [Required(ErrorMessage = "商户订单号  不能这空")]
        public string Partner_Trade_No { get; set; }

        /// <summary>
        /// 商户appid下，某用户的openid
        /// </summary>
        [Required(ErrorMessage = "用户的openid 不能这空")]
        public string OpenId { get; set; }

        /// <summary>
        /// 校验用户姓名选项(NO_CHECK：不校验真实姓名 FORCE_CHECK：强校验真实姓名)
        /// </summary>
        [Required(ErrorMessage = "Check_Name 不能这空")]
        public string Check_Name { get; set; }

        /// <summary>
        /// 收款用户真实姓名。 如果check_name设置为FORCE_CHECK，则必填用户真实姓名
        /// </summary>
       // [Required(ErrorMessage = "收款用户真实姓名")]
        public string Re_User_Name { get; set; }

        /// <summary>
        /// 企业付款金额，单位为分
        /// </summary>
        [Range(100L, long.MaxValue, ErrorMessage = "企业付款金额1元")]
        public long Amount { get; set; }

        /// <summary>
        /// 企业付款操作说明信息。必填。
        /// </summary>
        [Required(ErrorMessage = "企业付款操作说明信息 不能这空")]
        public string Desc { get; set; }

        /// <summary>
        /// 调用接口的机器Ip地址
        /// </summary>
        [Required(ErrorMessage = "调用接口的机器Ip地址 不能这空")]
        public string Spbill_Create_Ip { get; set; }

        private const string URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected override bool IsAddSignType()
        {
            return false;
        }

        /// <summary>
        /// 生成
        /// </summary>
        /// <param name="channel">通道</param>
        /// <param name="config">配置</param>
        /// <returns></returns>
        public ITransfersApplyResult Build(ITradeChannel channel, WeiXinConfigure config)
        {
            Validate(channel);
            string requestXml = BuildSignXmlParam(channel, config, "sign", "sign_type");
            byte[] cert = config.ConfigureInfo.RefundCretRaw();
            if (cert == null)
            {
                channel.ThrowChannelValidationException("未配置微信双向证书");
            }
            HttpClient client = new HttpClient();
            var certificate = RsaUtils.CreateCertificate(cert, config.ConfigureInfo.AccountId);
            client.Certificates.Add(certificate);
            var result = client.PostString(new Uri(URL), requestXml);
            TransfersResponse res = new TransfersResponse(result);            
            return res.ToResult(channel, apply);
        }
    }
}
